<?php
declare (strict_types=1);

namespace addons\Builder\driver;

use addons\Builder\facade\Builder;
use think\Exception;
use think\facade\Event;
use think\Model;
use think\model\concern\SoftDelete;

class TableModelBase extends Model
{

    use SoftDelete;

    protected $deleteTime = 'delete_time';

    protected $defaultSoftDelete = 0;

    protected function readTransform($value, array|string $type)
    {
        return empty($value) ? '' : parent::readTransform($value, $type);
    }

    public static function getTableList($tableCache, $param, $filed = '*', $model = ''): array
    {
        try {
            $export = isset($param['export']) && $param['export'] == 1 ? 1 : 0;
            if ($tableCache['takeOver'] == 1) {
                return $model::getTakeOverTableList($tableCache, $param, $filed, $export);
            }
            $that = parent::field($filed);
            foreach ($tableCache['extra_map'] as $k => $v) {
                $that->where($v[0], $v[1], $v[2]);
            }
            if ($tableCache['withTrashed'] && !$tableCache['onlyTrashed']) $that->withTrashed();
            if (!$tableCache['withTrashed'] && $tableCache['onlyTrashed']) $that->onlyTrashed();
            foreach ($tableCache['search'] as $v) {
                if ($v['type'] != 'linkage' && empty($param[$v['key']])) continue;
                $key = str_replace("__", "|", $v['key']);
                switch ($v['type']) {
                    case "linkage":
                        $keyAll = explode(',', $v['key']);
                        foreach ($keyAll as $item) {
                            if (!empty($param[$item])) {
                                $that->where($item, $param[$item]);
                            }
                        }
                        break;
                    case "date":
                        $start = strtotime(date('Y-m-d', $param[$v['key']]));
                        $end = strtotime(date('Y-m-d', $param[$v['key']])) + 86399;
                        $that->whereBetweenTime($key, $start, $end);
                        break;
                    case "time":
                        $times = explode(' - ', $param[$v['key']]);
                        $that->whereBetweenTime($key, strtotime($times[0]), strtotime($times[1]));
                        break;
                    default:
                        if (!empty($v['hasModel'])) {
                            $field = explode(',', $v['hasModelField']);
                            $ids = $v['hasModel']::where($field[0], $param[$v['key']])->column($field[1]);
                            $that->whereIn($v['key'], $ids);
                            break;
                        }
                        if (in_array($v['index'], ['=', '<>', '>', '>=', '<', '<='])) {
                            $that->where($key, $v['index'], $param[$v['key']]);
                        } else {
                            $method = 'where' . $v['index'];
                            match ($v['index']) {
                                'Like', 'NetLike' => $that->$method($key, '%' . $param[$v['key']] . '%'),
                                default => $that->$method($key, $param[$v['key']])
                            };
                        }

                }
            }
            $census = [];
            if (!empty($tableCache['census'])) {
                $method = $tableCache['census']['method'];
                $param['that'] = $that;
                $census = $tableCache['census']['model']::$method($param);
            }

            $count = 0;
            if (!$export) {
                $count = getCount($that->fetchSql()->select());
                $that->page(intval($param['page'] ?? 1), intval($param['limit'] ?? 10));
            } else {
                //临时提高内存
                ini_set('memory_limit', '1024M');
            }
            if (!empty($tableCache['hasOne'])) {
                $that->with($tableCache['hasOne']);
            }
            if ($tableCache['takeOver'] == 2) {
                return $model::getTakeOverTableList($that, $param, $filed);
            }
            if (isset($param['tableSortField']) && $param['tableSortField']) {
                $that->order($param['tableSortField'], $param['tableSortOrder']);
            } else {
                $that->order($tableCache['sort'] ?: ['create_time' => 'desc']);
            }
            $list = $that->select();
            if (!empty($tableCache['append'])) {
                $list->append($tableCache['append']);
            }
            if ($tableCache['takeOver'] == 3) {
                return $model::getTakeOverTableList($list, $param, $filed, $count);
            }
            return ['code' => 0, 'data' => $list, 'count' => $count, 'census' => $census];
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    public static function _magic($param, $logs): array
    {
        self::startTrans();
        try {
            if (isset($param['id']) && $param['id']) {
                $original = self::where($logs['pk'], $param[$logs['pk']])->find();
                if (empty($original)) {
                    return ['code' => -1, 'msg' => '记录不存在，请检查！'];
                }
                $logs['original'] = $original;
                $model = self::update($param);
                $logs['operation'] = 'save';
            } else {
                $model = self::create($param);
                $logs['operation'] = 'create';
            }
            if ($logs['writeLog']) {
                $logs['model'] = $model;
                Event::trigger('Logs', $logs);
            }
            self::commit();
            return ['code' => 1, 'msg' => '操作成功'];
        } catch (\Exception $e) {
            self::rollback();

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function _update($param, $logs): array
    {
        try {
            if (in_array($param['val'], ['true', 'false'])) {
                $val = $param['val'] == 'true' ? 1 : $param['val'];
                $val = $val == 'false' ? 0 : $val;
                $logs['valTitle'] = $val ? '开启' : '关闭';
            } else {
                $val = $param['val'];
                $logs['valTitle'] = $param['val'];
            }
            $key = $param['key'];
            if (is_array($param['id'])) {
                $model = self::update([$key => $val], [$logs['pk'] => $param['id']]);
                $logs['operation'] = 'updateAll';
                $model->ids = $param['id'];
            } else {
                $model = self::where($logs['pk'], $param['id'])->find();
                $model->$key = $val;
                $model->save();
                $logs['operation'] = 'update';
            }
            if ($logs['writeLog']) {
                $logs['model'] = $model;
                $logs['filedTitle'] = isset($param['tableUniqueStr']) ? Builder::TableCache()->getTableField($param['tableUniqueStr'], $key) : '';
                Event::trigger('Logs', $logs);
            }
            return ['code' => 1, 'msg' => '操作成功'];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public static function _delete($param, $logs): array
    {
        try {
            if (is_array($param['id'])) {
                self::destroy($param['id']);
                $model = (object)[];
                $logs['operation'] = 'deleteAll';
                $model->ids = $param['id'];
            } else {
                $model = self::where($logs['pk'], $param['id'])->find();
                self::destroy($param['id']);
                $logs['operation'] = 'delete';
            }
            if ($logs['writeLog']) {
                $logs['model'] = $model;
                Event::trigger('Logs', $logs);
            }
            return ['code' => 1, 'msg' => '已删除'];
        } catch (\Exception $e) {
            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }


    /**
     * @param array $map - 查询条件，数组格式
     * @param bool $merge - 是否合并公共查询条件
     * @param string $sort - 排序
     * @param array $with - 是否关键查询
     * @return TableModelBase[]|array|\think\Collection
     * 原点 2021年12月22日10:21:58 获取所有数据
     */
    public static function getList($map = [], $merge = true, $sort = 'sort', $with = [], $field = '*')
    {
        try {

            $map = $merge ? array_merge($map, ['status' => 1]) : $map;

            $that = !empty($with) ? parent::with($with)->where($map) : parent::where($map);

            return $that->order($sort, 'desc')->field($field)->select();

        } catch (\Exception $e) {

            return [];

        }
    }

    /**
     * @param array $map - 查询条件，数组格式
     * @param string $field - 查询字段，默认*
     * @param int $page - 当前页
     * @param int $limit - 每页条数，默认20
     * @param bool $merge - 是否合并is_del，status等公共状态查询条件
     * @param array $with - 是否关键查询
     * @return array
     * 原点 2021年12月22日11:26:47 分页获取数据
     */
    public static function getPageList($map = [],
                                       $field = '*',
                                       $page = 1,
                                       $limit = 20,
                                       $merge = true,
                                       $with = [],
                                       $in = [],
                                       $sort = [],
                                       $like = [],
                                       $time = [], $withoutField = '', $append = [])
    {
        try {

            $map = $merge ? array_merge($map, ['status' => 1]) : $map;


            $that = !empty($with) ? parent::with($with)->where($map) : parent::where($map);
            if (!empty($like)) {
                $that->whereLike($like['field'], '%' . $like['keyword'] . '%');
            }
            if ($time) {
                foreach ($time as $k => $v) {
                    $times = explode(' - ', $v['value']);
                    $that->whereBetweenTime($v['key'], $times[0], $times[1]);
                }
            }
            if (!empty($in)) {
                foreach ($in as $k => $v) {
                    $that->whereIn($k, $v);
                }
            }
            if ($withoutField) {
                $that->withoutField($withoutField);
            } else {
                $that->field($field);
            }
            $count = $that->count();
            $that->page(intval($page), intval($limit));
            if (!$sort) {
                $that->order($merge ? 'sort' : 'create_time', 'desc');
            } else {
                $that->order($sort['key'], $sort['value']);
            }
            $list = $that->select();
            if ($append) {
                $list->append($append);
            }
            $allPage = intval(ceil($count / $limit));
            return ['code' => 1, 'msg' => 'success', 'data' => $list, 'pages' => $allPage];

        } catch (\Exception $e) {

            return ['code' => $e->getCode(), 'message' => $e->getMessage()];

        }
    }


}
